//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
/* list.h */

/*
 * Linked lists support
 *
 * Copyright (C) 2002 Alexandre Julliard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __LIST_H__
#define __LIST_H__

#include "linkage.h"

struct list
{
    struct list *next;
    struct list *prev;
};

/* add an element after the specified one */
INLINE void list_add_after(struct list *elem, struct list *to_add)
{
    to_add->next = elem->next;
    to_add->prev = elem;
    elem->next->prev = to_add;
    elem->next = to_add;
}

/* add an element before the specified one */
INLINE void list_add_before(struct list *elem, struct list *to_add)
{
    to_add->next = elem;
    to_add->prev = elem->prev;
    elem->prev->next = to_add;
    elem->prev = to_add;
}

/* add element at the head of the list */
INLINE void list_add_head(struct list *list, struct list *elem)
{
    list_add_after( list, elem );
}

/* add element at the tail of the list */
INLINE void list_add_tail(struct list *list, struct list *elem)
{
    list_add_before( list, elem );
}

/* remove an element from its list */
INLINE void list_remove(struct list *elem)
{
    elem->next->prev = elem->prev;
    elem->prev->next = elem->next;
}

/* get the next element */
INLINE struct list *list_next(struct list *list, struct list *elem)
{
    struct list *ret = elem->next;
    if (elem->next == list) ret = NULL;
    return ret;
}

/* get the previous element */
INLINE struct list *list_prev(struct list *list, struct list *elem)
{
    struct list *ret = elem->prev;
    if (elem->prev == list) ret = NULL;
    return ret;
}

/* get the first element */
INLINE struct list *list_head(struct list *list)
{
    return list_next( list, list );
}

/* get the last element */
INLINE struct list *list_tail(struct list *list)
{
    return list_prev( list, list );
}

/* check if a list is empty */
INLINE int list_empty(struct list *list)
{
    return list->next == list;
}

/* initialize a list */
INLINE void list_init(struct list *list)
{
    list->next = list->prev = list;
}

/* iterate through the list */
#define LIST_FOR_EACH(cursor,list) \
    for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)

/* iterate through the list, with safety against removal */
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list) \
    for ((cursor) = (list)->next, (cursor2) = (cursor)->next; \
         (cursor) != (list); \
         (cursor) = (cursor2), (cursor2) = (cursor)->next)

/* iterate through the list using a list entry */
#define LIST_FOR_EACH_ENTRY(elem, list, type, field) \
    for ((elem) = LIST_ENTRY((list)->next, type, field); \
         &(elem)->field != (list); \
         (elem) = LIST_ENTRY((elem)->field.next, type, field))

/* iterate through the list using a list entry, with safety against removal */
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field) \
    for ((cursor) = LIST_ENTRY((list)->next, type, field), \
         (cursor2) = LIST_ENTRY((cursor)->field.next, type, field); \
         &(cursor)->field != (list); \
         (cursor) = (cursor2), \
         (cursor2) = LIST_ENTRY((cursor)->field.next, type, field))

/* macros for statically initialized lists */
#define LIST_INIT(list)  { &(list), &(list) }

/* get pointer to object containing list element */
#define LIST_ENTRY(elem, type, field) \
    ((type *)((char *)(elem) - (unsigned int)(&((type *)0)->field)))

#endif /* __LIST_H__ */
